package com.xiaotao.service.impl;

import cn.dev33.satoken.secure.SaSecureUtil;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.fastjson.JSONObject;
import com.nimbusds.jose.JOSEException;
import com.xiaotao.entity.User;
import com.xiaotao.entity.Wallet;
import com.xiaotao.mapper.UserMapper;
import com.xiaotao.mapper.WalletMapper;
import com.xiaotao.service.UserService;
import com.xiaotao.util.*;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

@Service
public class UserServiceImpl implements UserService {
    @Resource
    private UserMapper userMapper;
    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private RedisTemplate redisTemplateInit;
    @Resource
    private WalletMapper walletMapper;
    @Resource
    private MinioUtil minioUtil;

    @Override
    public ResponseUtil queryAll() {
        List<User> users = userMapper.queryAll();
        return users != null ? ResponseUtil.get(ResponseEnum.OK, users)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil queryById(Integer id) {
        User user = userMapper.queryById(id);
        return user != null ? ResponseUtil.get(ResponseEnum.OK, user)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil add(User user) {
        Integer add = userMapper.add(user);
        return add > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil update(User user) {
        Integer update = userMapper.update(user);
        return update > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil delete(Integer id) {
        Integer delete = userMapper.delete(id);
        return delete > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil registered(User user) {
        if (user.getUsername() == null || user.getUsername() == "" || user.getPassword() == "" || user.getPassword() == null || user.getPhone() == "" || user.getPhone() == null) {
            return ResponseUtil.getError(400, "账号、密码或手机号不能为空");
        }
        User user1 = userMapper.queryByUsername(user.getUsername());
        if (user1 != null) {
            return ResponseUtil.getError(400, "账号已存在");
        }
        User user3 = userMapper.queryByPhone(user.getPhone());
        if (user3!=null){
            return ResponseUtil.getError(400,"改手机号已注册过账号");
        }
        Object o = redisTemplateInit.opsForValue().get("verify" + user.getPhone());
        String string = String.valueOf(o);
        if (string == null) {
            return ResponseUtil.getError(400, "验证码已过期");
        }
        if (!string.equals(user.getVerify())) {
            return ResponseUtil.getError(400, "验证码错误");
        }
        if (user.getVerify() == null || user.getVerify() == "") {
            return ResponseUtil.getError(400, "输入验证码");
        }
        String password = user.getPassword();
        String replace = UUID.randomUUID().toString().replace("-", "");
        user.setSalt(replace);
        String s = SaSecureUtil.md5(SaSecureUtil.md5(password) + replace);
        user.setPassword(s);
        String substring = replace.substring(0, 4);
        user.setNickname("昵称" + substring);
        Integer add = userMapper.add(user);
        //注册同时添加钱包
        User user2 = userMapper.queryByUsername(user.getUsername());
        Wallet wallet = new Wallet();
        wallet.setUserId(user2.getId());
        walletMapper.add(wallet);
        redisTemplateInit.delete("verify" +user.getPhone());
        return add > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil login(User user) throws JOSEException {
        if (user.getUsername() == null || user.getUsername() == "" || user.getPassword() == "" || user.getPassword() == null) {
            return ResponseUtil.getError(400, "账号或密码不能为空");
        }
        User user1 = userMapper.queryByUsername(user.getUsername());
        if (user1 == null) {
            return ResponseUtil.getError(400, "账号不存在");
        } else if (!user1.getPassword().equals(SaSecureUtil.md5(user.getPassword() + user1.getSalt()))) {
            return ResponseUtil.getError(400, "密码错误");
        } else {
            user.setPassword(null);
            user.setSalt(null);
            Map<String, Object> map = new HashMap<>();
            map.put("user", user1);
            map.put("id", user1.getId());
            String token = JwtUtil.getToken(map);
            //修改token
            stringRedisTemplate.opsForValue().set("token" + user1.getId(), token, 30000, TimeUnit.SECONDS);
            return ResponseUtil.get(ResponseEnum.OK, token);
        }
    }

    @Override
    public ResponseUtil verify(User user) throws Exception {
        // 1. 保留原参数校验逻辑（优化空字符串判断，避免 == "" 的坑）
        if (StringUtils.isEmpty(user.getUsername()) || StringUtils.isEmpty(user.getPassword())) {
            return ResponseUtil.getError(400, "账号或密码不能为空");
        }
        String phoneRegex = "^1[3-9]\\d{9}$";
        boolean isPhoneValid = Pattern.matches(phoneRegex, user.getPhone());
        if (!isPhoneValid) {
            return ResponseUtil.getError(400, "请输入正确的手机号");
        }

        String mobile = user.getPhone();

        // 2. 复用 SmsCodeController 的逻辑：本地生成 6 位随机验证码（接口不支持 auto）
        String verifyCode = generateRandomCode(6);
        System.out.println("生成的验证码：" + verifyCode);

        // 3. 复用阿里云短信接口配置（和 sendSmsCode 完全一致，避免重复硬编码）
        String HOST = "https://gyytz.market.alicloudapi.com";
        String PATH = "/sms/smsSend";
        String METHOD = "POST";
        String APP_CODE = "a8316032089743b1bb0108892e8cea58";
        String SMS_SIGN_ID = "2e65b1bb3d054466b82f0c9d125465e2";
        String TEMPLATE_ID = "908e94ccf08b4476ba6c876d13f084ad";

        // 4. 构建请求参数（关键：修正 param 格式，和 sendSmsCode 一致，避免 1321 错误）
        Map<String, String> headers = new HashMap<>();
        headers.put("Authorization", "APPCODE " + APP_CODE);

        Map<String, String> querys = new HashMap<>();
        querys.put("mobile", mobile);
        querys.put("smsSignId", SMS_SIGN_ID);
        querys.put("templateId", TEMPLATE_ID);
        // 核心修正：去掉 auto，传本地生成的具体验证码，格式和 sendSmsCode 完全一致（双星号+无空格）
        querys.put("param", "**code**:" + verifyCode + ",**minute**:5");

        Map<String, String> bodys = new HashMap<>();

        try {
            // 5. 调用阿里云短信接口（复用 sendSmsCode 的调用逻辑）
            HttpResponse response = HttpUtils.doPost(HOST, PATH, METHOD, headers, querys, bodys);
            HttpEntity entity = response.getEntity();
            String responseStr = entity != null ? EntityUtils.toString(entity, "UTF-8") : "";
            System.out.println("阿里云短信接口返回：" + responseStr);

            // 6. 解析响应结果（完全对齐 SmsCodeController 的解析逻辑，适配实际返回格式）
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode != 200) {
                return ResponseUtil.getError(500, "验证码发送失败：HTTP状态码=" + statusCode + "，响应=" + responseStr);
            }

            if (StringUtils.isEmpty(responseStr)) {
                return ResponseUtil.getError(500, "验证码发送失败：阿里云接口返回空内容");
            }

            JSONObject responseJson = JSONObject.parseObject(responseStr);
            int bizCode = responseJson.getIntValue("code"); // 适配接口返回的 code 字段
            String msg = responseJson.getString("msg");     // 适配接口返回的 msg 字段

            // 7. 校验短信发送结果（按接口实际逻辑：bizCode=0 表示成功）
            if (bizCode != 0) {
                return ResponseUtil.getError(500, "验证码发送失败：" + msg);
            }

            // 8. 存 Redis（和 SmsCodeController 保持一致的 Key 格式："code"+mobile，避免查不到）
            redisTemplateInit.opsForValue().set("verify" + mobile, verifyCode, 300, TimeUnit.SECONDS);
            System.out.println("验证码已存储至 Redis：Key=verify" + mobile + "，Value=" + verifyCode + "，有效期5分钟");

            // 9. 返回成功结果（和原逻辑一致，返回验证码给前端）
            return ResponseUtil.get(ResponseEnum.VERIFY, verifyCode);

        } catch (Exception e) {
            e.printStackTrace();
            return ResponseUtil.getError(500, "验证码发送异常：" + e.getMessage());
        }
    }

    // 10. 复用 SmsCodeController 的随机验证码生成方法（本地生成，避免重复代码）
    private String generateRandomCode(int length) {
        if (length <= 0) {
            length = 6;
        }
        Random random = new Random();
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < length; i++) {
            sb.append(random.nextInt(10));
        }
        return sb.toString();
    }

    @Override
    public ResponseUtil queryByUserId(Integer id) {
        User user = userMapper.queryByUserId(id);
        return user != null ? ResponseUtil.get(ResponseEnum.OK, user)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil updateUser(User user) {
        Integer update = userMapper.updateUser(user);
        return update > 0 ? ResponseUtil.get(ResponseEnum.OK)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public ResponseUtil exit() throws Exception {
        Integer id = UserUtil.UserContext();
        stringRedisTemplate.delete("token" + id);
        String token = stringRedisTemplate.opsForValue().get("token" + id);
        if (token == null) {
            return ResponseUtil.get(ResponseEnum.OK);
        } else {
            return ResponseUtil.get(ResponseEnum.FAIL);
        }
    }

    @Override
    public ResponseUtil findUserAvatar(Integer id) {
        User user = userMapper.findUserAvatar(id);
        return user != null ? ResponseUtil.get(ResponseEnum.OK, user)
                : ResponseUtil.get(ResponseEnum.FAIL);
    }

    @Override
    public Map<String, Object> uploadFile(MultipartFile file, String bucketName) throws Exception {
        Map<String, Object> map = minioUtil.uploadFile(file, bucketName);
        if ((int) map.get("code") == 200) {
            String imageUrl = (String) map.get("imageUrl");
            Integer userId = UserUtil.UserContext();
            User user = new User();
            user.setId(userId);
            user.setAvatar(imageUrl);
            userMapper.updateAvatar(user);
            map.put("msg", "头像更新成功");
        }
        return map;
    }

    @Override
    public ResponseUtil smsLogin(String mobile, String code) throws JOSEException {
        if (mobile == null || mobile == "" || code == null || code == "") {
            return ResponseUtil.getError(400, "手机号或验证码不能为空");
        }
        User user = userMapper.queryByPhone(mobile);
        if (user == null) {
            return ResponseUtil.getError(400, "该手机号未注册账号");
        }
        Object o = redisTemplateInit.opsForValue().get("code" + mobile);
        String string = String.valueOf(o);
        if (string == null) {
            return ResponseUtil.getError(400, "验证码已过期");
        }
        if (!string.equals(code)) {
            return ResponseUtil.getError(400, "验证码错误");
        }
        if (code == null || code == "") {
            return ResponseUtil.getError(400, "请输入验证码");
        }
        Map<String, Object> map = new HashMap<>();
        map.put("user", user);
        map.put("id", user.getId());
        String token = JwtUtil.getToken(map);
        stringRedisTemplate.opsForValue().set("token" + user.getId(), token, 30000, TimeUnit.SECONDS);
        return ResponseUtil.get(ResponseEnum.OK, token);
    }
}
